﻿using System;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

namespace Fotia.SqlClr
{
	public class FormatString
	{
		[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
		public static SqlString FormatString0(SqlString format, object arg0)
		{
			return format.IsNull ? SqlString.Null : string.Format(format.Value, SqlTypeToNetType(arg0));
		}

		[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
		public static SqlString FormatString1(SqlString format, object arg0, object arg1)
		{
			return format.IsNull ? SqlString.Null : string.Format(format.Value, SqlTypeToNetType(arg0, arg1));
		}

		[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
		public static SqlString FormatString2(SqlString format, object arg0, object arg1, object arg2)
		{
			return format.IsNull ? SqlString.Null : string.Format(format.Value, SqlTypeToNetType(arg0, arg1, arg2));
		}

		[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
		public static SqlString FormatString3(SqlString format, object arg0, object arg1, object arg2, object arg3)
		{
			return format.IsNull ? SqlString.Null : string.Format(format.Value, SqlTypeToNetType(arg0, arg1, arg2, arg3));
		}

		private static object[] SqlTypeToNetType(params object[] sqlValue)
		{
			return Array.ConvertAll<object, object>(sqlValue, ConvertSqlTypeToNetType);
		}

		private static object ConvertSqlTypeToNetType(object sqlValue)
		{
			var nullabe = sqlValue as INullable;
			if((nullabe == null) || (nullabe.IsNull))
				return null;

			if(sqlValue is SqlString)
				return ((SqlString)sqlValue).Value;
			if(sqlValue is SqlInt16)
				return ((SqlInt16)sqlValue).Value;
			if(sqlValue is SqlInt32)
				return ((SqlInt32)sqlValue).Value;
			if(sqlValue is SqlInt64)
				return ((SqlInt64)sqlValue).Value;
			if(sqlValue is SqlSingle)
				return ((SqlSingle)sqlValue).Value;
			if(sqlValue is SqlDouble)
				return ((SqlDouble)sqlValue).Value;
			if(sqlValue is SqlDateTime)
				return ((SqlDateTime)sqlValue).Value;
			if(sqlValue is SqlMoney)
				return ((SqlMoney)sqlValue).Value;
			if(sqlValue is SqlDecimal)
				return ((SqlDecimal)sqlValue).Value;
			if(sqlValue is SqlBoolean)
				return ((SqlBoolean)sqlValue).Value;
			if(sqlValue is SqlByte)
				return ((SqlByte)sqlValue).Value;
			if(sqlValue is SqlGuid)
				return ((SqlGuid)sqlValue).Value;
			if(sqlValue is SqlXml)
				return ((SqlXml)sqlValue).Value;
			return sqlValue;
		}
	}
}